package com.junglone.gateway.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;

/**
 * Description:
 *
 * @author junglone: <a href="mailto:cjlnzb@hotmail.com">cjlnzb@hotmail.com</a>
 * @since 2020/09/24 16:18
 */
@Component
public class MyCustomGatewayFilterFactory
        extends AbstractGatewayFilterFactory<MyCustomGatewayFilterFactory.Config> {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyCustomGatewayFilterFactory.class);

    /**
     * METHOD key.
     */
    public static final String METHOD = "method";

    public MyCustomGatewayFilterFactory() {

        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList(METHOD);
    }

    @Override
    public GatewayFilter apply(Config config) {
        // grab configuration from Config object
        return (exchange, chain) -> {

            ServerHttpResponse response = exchange.getResponse();

            String strMethod = exchange.getRequest().getMethod().name();

            LOGGER.info("request.method == {} ========= config.method == {}", strMethod, config.getMethod());
            String strAuth = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
            LOGGER.info("received AUTHORIZATION == {}", strAuth);

            // 只允许指定的请求方式
            if (strMethod.equalsIgnoreCase(config.getMethod())) {
                // 重新设置授权信息并流转到下游服务
                ServerHttpRequest mutableReq = exchange.getRequest().mutate()
                        // 使用 add 方法设置请求头, 不会覆盖原本已有的值
                        .headers(httpHeaders -> {
                            httpHeaders.set(HttpHeaders.AUTHORIZATION, "hello MyCustomGatewayFilterFactory");
                        }).build();
                ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();

                return chain.filter(mutableExchange);
            }
            else {
                byte[] bits = "not allowed".getBytes(StandardCharsets.UTF_8);
                DataBuffer buffer = response.bufferFactory().wrap(bits);
                response.setStatusCode(HttpStatus.OK);
                response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
                return response.writeWith(Mono.just(buffer));
            }

        };
    }


    /**
     * Description:
     *
     * @author junglone: <a href="mailto:cjlnzb@hotmail.com">cjlnzb@hotmail.com</a>
     * @since 2020/09/24 16:19
     */
    public static class Config {

        private String method;

        public String getMethod() {

            return method;
        }

        public void setMethod(String method) {

            this.method = method;
        }

    }

}
